home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / Water / CWaterApp.cpp < prev    next >
C/C++ Source or Header  |  2001-10-31  |  24KB  |  798 lines

  1. //-----------------------------------------------------------------------------
  2. // File: CWaterApp.cpp
  3. //
  4. // Desc: 
  5. //
  6. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <tchar.h>
  10. #include <stdio.h>
  11. #include <d3dx8.h>
  12. #include "D3DApp.h"
  13. #include "D3DFont.h"
  14. #include "DXUtil.h"
  15. #include "CEnvironment.h"
  16. #include "CWater.h"
  17. #include "resource.h"
  18.  
  19. #define WATER_DEPTH 20.0f
  20. #define WATER_CAUSTICS_SIZE 128
  21.  
  22.  
  23.  
  24. //-----------------------------------------------------------------------------
  25. // Name: CMyD3DApplication
  26. // Desc: 
  27. //-----------------------------------------------------------------------------
  28. class CMyD3DApplication : public CD3DApplication
  29. {
  30. public:
  31.     CMyD3DApplication();
  32.     HRESULT GetNextTechnique(INT nDir, BOOL bBypassValidate);
  33.  
  34.     virtual HRESULT OneTimeSceneInit();
  35.     virtual HRESULT InitDeviceObjects();
  36.     virtual HRESULT RestoreDeviceObjects();
  37.     virtual HRESULT InvalidateDeviceObjects();
  38.     virtual HRESULT DeleteDeviceObjects();
  39.     virtual HRESULT FrameMove();
  40.     virtual HRESULT Render();
  41.  
  42.     virtual LRESULT MsgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  43.  
  44.  
  45. private:
  46.     // Water    
  47.     CWater                 m_Water;
  48.     CEnvironment           m_Environment;
  49.  
  50.     LPD3DXEFFECT           m_pEffect;
  51.     UINT_PTR                   m_iTechnique;
  52.     LPD3DXRENDERTOSURFACE  m_pRenderToSurface;
  53.  
  54.     D3DXVECTOR4            m_vecLight;
  55.     D3DXCOLOR              m_colorLight;
  56.  
  57.     LPDIRECT3DTEXTURE8     m_pFloorTex;
  58.     LPDIRECT3DTEXTURE8     m_pCausticTex;
  59.     LPDIRECT3DSURFACE8     m_pCausticSurf;
  60.     LPDIRECT3DTEXTURE8     m_pSkyTex[6];
  61.     LPDIRECT3DCUBETEXTURE8 m_pSkyCubeTex;
  62.  
  63.     CD3DFont*              m_pFont;
  64.     CD3DFont*              m_pFontSmall;
  65.  
  66.     // Interface
  67.     BYTE        m_bKey[256];
  68.  
  69.     BOOL        m_bPause;
  70.     BOOL        m_bDrawWater;
  71.     BOOL        m_bDrawCaustics;
  72.     BOOL        m_bDrawEnvironment;
  73.     BOOL        m_bShowHelp;
  74.  
  75.     FLOAT       m_fSpeed;
  76.     FLOAT       m_fAngularSpeed;
  77.     FLOAT       m_fTime;
  78.     FLOAT       m_fSecsPerFrame;
  79.  
  80.     D3DXVECTOR3 m_vecVelocity;
  81.     D3DXVECTOR3 m_vecAngularVelocity;
  82.  
  83.     D3DXMATRIX  m_matIdentity;
  84.     D3DXMATRIX  m_matView;
  85.     D3DXMATRIX  m_matPosition;
  86.     D3DXMATRIX  m_matProjection;
  87. };
  88.  
  89.  
  90.  
  91.  
  92. //-----------------------------------------------------------------------------
  93. // Name: WinMain()
  94. // Desc: Entry point to the program. Initializes everything, and goes into a
  95. //       message-processing loop. Idle time is used to render the scene.
  96. //-----------------------------------------------------------------------------
  97. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  98. {
  99.     CMyD3DApplication d3dApp;
  100.  
  101.     if(FAILED(d3dApp.Create(hInst)))
  102.         return 0;
  103.  
  104.     return d3dApp.Run();
  105. }
  106.  
  107.  
  108.  
  109.  
  110. //-----------------------------------------------------------------------------
  111. // Name: CMyD3DApplication
  112. // Desc:
  113. //-----------------------------------------------------------------------------
  114. CMyD3DApplication::CMyD3DApplication()
  115. {
  116.     m_strWindowTitle    = _T("Water");
  117.     m_bUseDepthBuffer   = TRUE;
  118.  
  119.     m_pFont         = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  120.     m_pFontSmall    = new CD3DFont( _T("Arial"),  9, D3DFONT_BOLD );
  121.  
  122.     // Water
  123.     m_pEffect       = NULL;
  124.     m_iTechnique    = 0;
  125.  
  126.     m_vecLight      = D3DXVECTOR4(0.5f, -1.0f, 1.0f, 0.0f);
  127.     m_colorLight    = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
  128.  
  129.     m_pFloorTex     = NULL;
  130.     m_pCausticTex   = NULL;
  131.     m_pCausticSurf  = NULL;
  132.     m_pSkyCubeTex   = NULL;
  133.  
  134.     for(UINT i = 0; i < 6; i++)
  135.         m_pSkyTex[i] = NULL;
  136.  
  137.     // Misc
  138.     memset(m_bKey, 0x00, sizeof(m_bKey));
  139.  
  140.     m_fSpeed        = 25.0f;
  141.     m_fAngularSpeed = 1.0f;
  142.     m_fSecsPerFrame = 0.0f;
  143.     m_fTime         = 0.0f;
  144.  
  145.     m_vecVelocity        = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  146.     m_vecAngularVelocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  147.  
  148.     D3DXMatrixIdentity(&m_matIdentity);
  149.     D3DXMatrixIdentity(&m_matView);
  150.     D3DXMatrixIdentity(&m_matPosition);
  151.     D3DXMatrixIdentity(&m_matProjection);
  152.  
  153.     m_bShowHelp         = FALSE;
  154.     m_bPause            = FALSE;
  155. }
  156.  
  157.  
  158.  
  159.  
  160. //-----------------------------------------------------------------------------
  161. // Name: GetNextTechnique
  162. // Desc:
  163. //-----------------------------------------------------------------------------
  164. HRESULT CMyD3DApplication::GetNextTechnique(INT nDir, BOOL bBypassValidate)
  165. {
  166.     D3DXEFFECT_DESC effect;
  167.     UINT_PTR iTechnique = m_iTechnique;
  168.  
  169.     m_pEffect->GetDesc(&effect);
  170.  
  171.     for(;;)
  172.     {
  173.         iTechnique += nDir;
  174.  
  175.         if(((INT_PTR) iTechnique) < 0)
  176.             iTechnique = effect.Techniques - 1;
  177.  
  178.         if(iTechnique >= effect.Techniques)
  179.             iTechnique = 0;
  180.  
  181.         if(nDir && (iTechnique == m_iTechnique))
  182.             break;
  183.  
  184.         if(!nDir)
  185.             nDir = 1;
  186.  
  187.  
  188.         m_pEffect->SetTechnique((LPCSTR) iTechnique);
  189.  
  190.         if(bBypassValidate || (iTechnique == effect.Techniques - 1) || 
  191.           (m_bDrawCaustics || !m_pEffect->IsParameterUsed("tCAU")) && SUCCEEDED(m_pEffect->Validate()))
  192.         {
  193.             m_iTechnique = iTechnique;
  194.  
  195.             char szText[256];
  196.             sprintf(szText, "Water - Technique %d", m_iTechnique);
  197.             SetWindowText(m_hWnd, szText);
  198.  
  199.             return S_OK;
  200.         }
  201.     }
  202.  
  203.     m_pEffect->SetTechnique((LPCSTR) m_iTechnique);
  204.     return E_FAIL;
  205. }
  206.  
  207.  
  208.  
  209.  
  210. //-----------------------------------------------------------------------------
  211. // Name: OneTimeSceneInit
  212. // Desc:
  213. //-----------------------------------------------------------------------------
  214. HRESULT CMyD3DApplication::OneTimeSceneInit()
  215. {
  216.     HRESULT hr;
  217.  
  218.     // Initialize Water
  219.     if(FAILED(hr = m_Water.Initialize(64.0f, WATER_DEPTH)))
  220.         return hr;
  221.  
  222.     // Initialize Environment
  223.     if(FAILED(hr = m_Environment.Initialize(1000.0f)))
  224.         return hr;
  225.  
  226.     // Misc stuff
  227.     D3DXMatrixRotationX(&m_matPosition, D3DX_PI * -0.3f);
  228.     m_matPosition._42 = 15.0f;
  229.     m_matPosition._43 = 15.0f;
  230.  
  231.     D3DXMatrixInverse(&m_matView, NULL, &m_matPosition);
  232.     return S_OK;
  233. }
  234.  
  235.  
  236.  
  237.  
  238. //-----------------------------------------------------------------------------
  239. // Name: InitDeviceObjects
  240. // Desc:
  241. //-----------------------------------------------------------------------------
  242. HRESULT CMyD3DApplication::InitDeviceObjects()
  243. {
  244.     HRESULT hr;
  245.     TCHAR sz[512];
  246.  
  247.     m_bDrawWater        = TRUE;
  248.     m_bDrawCaustics     = TRUE;
  249.     m_bDrawEnvironment  = TRUE;
  250.  
  251.  
  252.     // Initialize the font's internal textures
  253.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  254.     m_pFontSmall->InitDeviceObjects( m_pd3dDevice );
  255.  
  256.     // Floor
  257.     DXUtil_FindMediaFile(sz, _T("Water.bmp"));
  258.     D3DXCreateTextureFromFileEx(m_pd3dDevice, sz, D3DX_DEFAULT, D3DX_DEFAULT, 
  259.         D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, 
  260.         D3DX_DEFAULT, 0, NULL, NULL, &m_pFloorTex);
  261.  
  262.  
  263.     // Sky
  264.     TCHAR* szSkyTex[6] =
  265.     {
  266.         _T("lobbyxpos.bmp"), _T("lobbyxneg.bmp"),
  267.         _T("lobbyypos.bmp"), _T("lobbyyneg.bmp"),
  268.         _T("lobbyzneg.bmp"), _T("lobbyzpos.bmp")
  269.     };
  270.  
  271.     for(UINT i = 0; i < 6; i++)
  272.     {
  273.         DXUtil_FindMediaFile(sz, szSkyTex[i]);
  274.         D3DXCreateTextureFromFileEx(m_pd3dDevice, sz, D3DX_DEFAULT, D3DX_DEFAULT, 
  275.             1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 
  276.             0, NULL, NULL, &m_pSkyTex[i]);
  277.     }
  278.  
  279.     if(SUCCEEDED(D3DXCreateCubeTexture(m_pd3dDevice, 128, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, &m_pSkyCubeTex)))
  280.     {
  281.         for(UINT i = 0; i < 6; i++)
  282.         {
  283.             if(m_pSkyTex[i])
  284.             {
  285.                 IDirect3DSurface8 *pSrc;
  286.                 IDirect3DSurface8 *pDest;
  287.  
  288.                 m_pSkyTex[i]->GetSurfaceLevel(0, &pSrc);
  289.                 m_pSkyCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES) i, 0, &pDest);
  290.  
  291.                 if(pSrc && pDest)
  292.                     D3DXLoadSurfaceFromSurface(pDest, NULL, NULL, pSrc, NULL, NULL, D3DX_DEFAULT, 0);
  293.  
  294.                 SAFE_RELEASE(pDest);
  295.                 SAFE_RELEASE(pSrc);
  296.             }
  297.         }
  298.  
  299.         D3DXFilterCubeTexture(m_pSkyCubeTex, NULL, 0, D3DX_DEFAULT);
  300.     }
  301.  
  302.  
  303.  
  304.     // OnCreateDevice
  305.     if(FAILED(hr = m_Water.OnCreateDevice(m_pd3dDevice)))
  306.         return hr;
  307.  
  308.     if(FAILED(hr = m_Environment.OnCreateDevice(m_pd3dDevice)))
  309.         return hr;
  310.  
  311.     return S_OK;
  312. }
  313.  
  314.  
  315.  
  316.     
  317. //-----------------------------------------------------------------------------
  318. // Name: RestoreDeviceObjects
  319. // Desc:
  320. //-----------------------------------------------------------------------------
  321. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  322. {
  323.     HRESULT hr;
  324.  
  325.     // Restore the font
  326.     m_pFont->RestoreDeviceObjects();
  327.     m_pFontSmall->RestoreDeviceObjects();
  328.  
  329.     // Create light
  330.     D3DLIGHT8 light;
  331.     ZeroMemory(&light, sizeof(light));
  332.  
  333.     light.Type        = D3DLIGHT_DIRECTIONAL;
  334.     light.Diffuse.r   = m_colorLight.r;
  335.     light.Diffuse.g   = m_colorLight.g;
  336.     light.Diffuse.b   = m_colorLight.b;
  337.     light.Diffuse.a   = m_colorLight.a;
  338.     light.Specular.r  = 1.0f;
  339.     light.Specular.g  = 1.0f;
  340.     light.Specular.b  = 1.0f;
  341.     light.Specular.a  = 0.0f;
  342.     light.Direction.x = m_vecLight.x;
  343.     light.Direction.y = m_vecLight.y;
  344.     light.Direction.z = m_vecLight.z;
  345.  
  346.     m_pd3dDevice->SetLight(0, &light);
  347.     m_pd3dDevice->LightEnable(0, TRUE);
  348.  
  349.  
  350.     // Create material
  351.     D3DMATERIAL8 material;
  352.     ZeroMemory(&material, sizeof(material));
  353.  
  354.     material.Diffuse.a  = 1.0f;
  355.     material.Specular.r = 0.5f;
  356.     material.Specular.g = 0.5f;
  357.     material.Specular.b = 0.5f;
  358.     material.Power      = 20.0f;
  359.  
  360.     m_pd3dDevice->SetMaterial(&material);
  361.  
  362.     // Setup render states
  363.     m_pd3dDevice->SetVertexShader(D3DFVF_XYZ);
  364.  
  365.     m_pd3dDevice->SetTransform(D3DTS_VIEW,  &m_matView);
  366.     m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_matIdentity);
  367.  
  368.     m_pd3dDevice->SetRenderState(D3DRS_LIGHTING,       FALSE);
  369.     m_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
  370.  
  371.     m_pd3dDevice->SetRenderState(D3DRS_ZFUNC,     D3DCMP_LESSEQUAL);
  372.     m_pd3dDevice->SetRenderState(D3DRS_CULLMODE,  D3DCULL_CW);
  373.     m_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
  374.     m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ONE);
  375.     m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  376.  
  377.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_DISABLE);
  378.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  379.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
  380.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  381.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  382.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  383.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  384.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  385.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  386.     m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
  387.  
  388.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_DISABLE);
  389.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  390.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
  391.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  392.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  393.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  394.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  395.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  396.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  397.     m_pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
  398.  
  399.  
  400.  
  401.  
  402.     // Create caustic texture
  403.     D3DDISPLAYMODE mode;
  404.     m_pd3dDevice->GetDisplayMode(&mode);
  405.  
  406.     if(FAILED(hr = D3DXCreateTexture(m_pd3dDevice, WATER_CAUSTICS_SIZE, WATER_CAUSTICS_SIZE, 1, D3DUSAGE_RENDERTARGET, mode.Format, D3DPOOL_DEFAULT, &m_pCausticTex)) &&
  407.        FAILED(hr = D3DXCreateTexture(m_pd3dDevice, WATER_CAUSTICS_SIZE, WATER_CAUSTICS_SIZE, 1, 0, mode.Format, D3DPOOL_DEFAULT, &m_pCausticTex)))
  408.     {
  409.         return hr;
  410.     }
  411.  
  412.     D3DSURFACE_DESC desc;
  413.     m_pCausticTex->GetSurfaceLevel(0, &m_pCausticSurf);
  414.     m_pCausticSurf->GetDesc(&desc);
  415.  
  416.     if(FAILED(hr = D3DXCreateRenderToSurface(m_pd3dDevice, desc.Width, desc.Height, 
  417.         desc.Format, FALSE, D3DFMT_UNKNOWN, &m_pRenderToSurface)))
  418.     {
  419.         return hr;
  420.     }
  421.  
  422.  
  423.  
  424.     // Shader
  425.     TCHAR sz[512];
  426.     DXUtil_FindMediaFile(sz, _T("water.sha"));
  427.  
  428.     if(FAILED(hr = D3DXCreateEffectFromFile(m_pd3dDevice, sz, &m_pEffect, NULL)))
  429.         return hr;
  430.  
  431.     m_pEffect->SetMatrix("mID",  &m_matIdentity);
  432.     m_pEffect->SetMatrix("mENV", &m_matIdentity);
  433.  
  434.     m_pEffect->SetTexture("tFLR", m_pFloorTex);
  435.     m_pEffect->SetTexture("tCAU", m_pCausticTex);
  436.     m_pEffect->SetTexture("tENV", m_pSkyCubeTex);
  437.  
  438.     if(FAILED(hr = GetNextTechnique(0, FALSE)))
  439.         return hr;
  440.  
  441.  
  442.     // Set surfaces
  443.     if(FAILED(hr = m_Environment.SetSurfaces(
  444.         m_pSkyTex[D3DCUBEMAP_FACE_NEGATIVE_X], m_pSkyTex[D3DCUBEMAP_FACE_POSITIVE_X], 
  445.         m_pSkyTex[D3DCUBEMAP_FACE_NEGATIVE_Y], m_pSkyTex[D3DCUBEMAP_FACE_POSITIVE_Y],
  446.         m_pSkyTex[D3DCUBEMAP_FACE_POSITIVE_Z], m_pSkyTex[D3DCUBEMAP_FACE_NEGATIVE_Z])))
  447.     {
  448.         return hr;
  449.     }
  450.  
  451.  
  452.     // OnResetDevice
  453.     if(FAILED(hr = m_Water.OnResetDevice()))
  454.         return hr;
  455.  
  456.     if(FAILED(hr = m_Environment.OnResetDevice()))
  457.         return hr;
  458.  
  459.     return S_OK;
  460. }
  461.  
  462.  
  463.  
  464.  
  465. //-----------------------------------------------------------------------------
  466. // Name: InvalidateDeviceObjects
  467. // Desc:
  468. //-----------------------------------------------------------------------------
  469. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  470. {
  471.     HRESULT hr;
  472.  
  473.     m_pFont->InvalidateDeviceObjects();
  474.     m_pFontSmall->InvalidateDeviceObjects();
  475.  
  476.     if(FAILED(hr = m_Water.OnLostDevice()))
  477.         return hr;
  478.  
  479.     if(FAILED(hr = m_Environment.OnLostDevice()))
  480.         return hr;
  481.  
  482.     SAFE_RELEASE(m_pRenderToSurface);
  483.     SAFE_RELEASE(m_pEffect);
  484.     SAFE_RELEASE(m_pCausticSurf);
  485.     SAFE_RELEASE(m_pCausticTex);
  486.  
  487.     return S_OK;
  488. }
  489.  
  490.  
  491.  
  492.  
  493. //-----------------------------------------------------------------------------
  494. // Name: DeleteDeviceObjects
  495. // Desc:
  496. //-----------------------------------------------------------------------------
  497. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  498. {
  499.     HRESULT hr;
  500.  
  501.     m_pFont->DeleteDeviceObjects();
  502.     m_pFontSmall->DeleteDeviceObjects();
  503.  
  504.     if(FAILED(hr = m_Water.OnDestroyDevice()))
  505.         return hr;
  506.  
  507.     if(FAILED(hr = m_Environment.OnDestroyDevice()))
  508.         return hr;
  509.  
  510.     SAFE_RELEASE(m_pFloorTex);
  511.     SAFE_RELEASE(m_pSkyCubeTex);
  512.  
  513.     for(UINT i = 0; i < 6; i++)
  514.         SAFE_RELEASE(m_pSkyTex[i]);
  515.  
  516.  
  517.     return S_OK;
  518. }
  519.  
  520.  
  521.  
  522.  
  523. //-----------------------------------------------------------------------------
  524. // Name: FrameMove
  525. // Desc:
  526. //-----------------------------------------------------------------------------
  527. HRESULT CMyD3DApplication::FrameMove()
  528. {
  529.     HRESULT hr;
  530.  
  531.     //
  532.     // Process keyboard input
  533.     //
  534.  
  535.     D3DXVECTOR3 vecT(0.0f, 0.0f, 0.0f);
  536.     D3DXVECTOR3 vecR(0.0f, 0.0f, 0.0f);
  537.  
  538.     if(m_bKey[VK_NUMPAD1] || m_bKey[VK_LEFT])  vecT.x -= 1.0f; // Slide Left
  539.     if(m_bKey[VK_NUMPAD3] || m_bKey[VK_RIGHT]) vecT.x += 1.0f; // Slide Right
  540.     if(m_bKey[VK_DOWN])                        vecT.y -= 1.0f; // Slide Down
  541.     if(m_bKey[VK_UP])                          vecT.y += 1.0f; // Slide Up
  542.     if(m_bKey['W'])                            vecT.z -= 2.0f; // Move Forward
  543.     if(m_bKey['S'])                            vecT.z += 2.0f; // Move Backward
  544.     if(m_bKey['A'] || m_bKey[VK_NUMPAD8])      vecR.x -= 1.0f; // Pitch Down
  545.     if(m_bKey['Z'] || m_bKey[VK_NUMPAD2])      vecR.x += 1.0f; // Pitch Up
  546.     if(m_bKey['E'] || m_bKey[VK_NUMPAD6])      vecR.y -= 1.0f; // Turn Right
  547.     if(m_bKey['Q'] || m_bKey[VK_NUMPAD4])      vecR.y += 1.0f; // Turn Left
  548.     if(m_bKey[VK_NUMPAD9])                     vecR.z -= 2.0f; // Roll CW
  549.     if(m_bKey[VK_NUMPAD7])                     vecR.z += 2.0f; // Roll CCW
  550.  
  551.     m_vecVelocity = m_vecVelocity * 0.9f + vecT * 0.1f;
  552.     m_vecAngularVelocity = m_vecAngularVelocity * 0.9f + vecR * 0.1f;
  553.  
  554.  
  555.  
  556.     //
  557.     // Update position and view matricies
  558.     //
  559.  
  560.     D3DXMATRIX matT, matR;
  561.     D3DXQUATERNION qR;
  562.  
  563.     vecT = m_vecVelocity * m_fElapsedTime * m_fSpeed;
  564.     vecR = m_vecAngularVelocity * m_fElapsedTime * m_fAngularSpeed;
  565.  
  566.     D3DXMatrixTranslation(&matT, vecT.x, vecT.y, vecT.z);
  567.     D3DXMatrixMultiply(&m_matPosition, &matT, &m_matPosition);
  568.  
  569.     D3DXQuaternionRotationYawPitchRoll(&qR, vecR.y, vecR.x, vecR.z);
  570.     D3DXMatrixRotationQuaternion(&matR, &qR);
  571.  
  572.     D3DXMatrixMultiply(&m_matPosition, &matR, &m_matPosition);
  573.     D3DXMatrixInverse(&m_matView, NULL, &m_matPosition);
  574.  
  575.  
  576.     //
  577.     // Update simulation
  578.     //
  579.  
  580.     if(!m_bPause && m_bDrawWater)
  581.     {
  582.         BOOL bCaustics = m_bDrawCaustics && m_pEffect->IsParameterUsed("tCAU");
  583.         D3DXVECTOR3 vecPos(m_matPosition._41, m_matPosition._42, m_matPosition._43);
  584.         D3DXVECTOR3 vecLight(0.0f, 1.0f, 0.0f);
  585.  
  586.         m_Water.Update(vecPos, vecLight, bCaustics);
  587.         m_fTime += m_fSecsPerFrame;
  588.  
  589.         if(bCaustics)
  590.         {
  591.             if(SUCCEEDED(m_pRenderToSurface->BeginScene(m_pCausticSurf, NULL)))
  592.             {
  593.                 D3DXMATRIX matProj;
  594.                 D3DXMATRIX matView;
  595.  
  596.                 D3DXMatrixOrthoRH(&matProj, 63.0f, 63.0f, 1.0f, 100.0f);
  597.                 D3DXMatrixRotationX(&matView, 0.5f * D3DX_PI);
  598.                 matView._43 = -50.0f;
  599.  
  600.                 m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
  601.                 m_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
  602.  
  603.                 m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0f, 0);
  604.  
  605.                 m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
  606.                 m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  607.                 m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  608.  
  609.                 m_Water.DrawCaustics();
  610.  
  611.                 m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  612.                 m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
  613.                 m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
  614.  
  615.                 m_pRenderToSurface->EndScene();
  616.             }
  617.             else
  618.             {
  619.                 m_bDrawCaustics = FALSE;
  620.                 m_pEffect->SetTexture("tCAU", NULL);
  621.  
  622.                 if(FAILED(hr = GetNextTechnique(0, FALSE)))
  623.                     return hr;
  624.             }
  625.         }
  626.     }
  627.  
  628.     return S_OK;
  629. }
  630.  
  631.  
  632.  
  633.  
  634. //-----------------------------------------------------------------------------
  635. // Name: Render
  636. // Desc:
  637. //-----------------------------------------------------------------------------
  638. HRESULT CMyD3DApplication::Render()
  639. {   
  640.     HRESULT hr;
  641.  
  642.     if(FAILED(hr = m_pd3dDevice->BeginScene()))
  643.         return hr;
  644.  
  645.     // Draw Environment
  646.     FLOAT fAspectRatio = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  647.     D3DXMatrixPerspectiveFovRH(&m_matProjection, D3DXToRadian(60.0f), fAspectRatio, 0.1f, 2000.0f);
  648.     m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &m_matProjection);    
  649.  
  650.     if(m_bDrawEnvironment)
  651.     {
  652.         D3DXMATRIX mat(m_matView);
  653.         mat._41 = mat._42 = mat._43 = 0.0f;
  654.         m_pd3dDevice->SetTransform(D3DTS_VIEW, &mat);
  655.  
  656.         m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  657.         m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  658.  
  659.         m_Environment.Draw();
  660.  
  661.         m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  662.         m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
  663.     }
  664.     else
  665.     {
  666.         m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  667.     }
  668.  
  669.     m_pd3dDevice->SetTransform(D3DTS_VIEW, &m_matView);
  670.  
  671.     // Draw water
  672.     if(m_bDrawWater)
  673.     {
  674.         // Setup matrices
  675.         if(m_pEffect->IsParameterUsed("mENV"))
  676.         {
  677.             D3DXMATRIX matP(m_matPosition);
  678.             matP._41 = matP._42 = matP._43 = 0.0f;
  679.  
  680.             D3DXMATRIX mat;
  681.             D3DXMatrixScaling(&mat, 1.0f, 1.0f, -1.0f);
  682.  
  683.             D3DXMatrixMultiply(&mat, &matP, &mat);
  684.  
  685.             // matCube
  686.             m_pEffect->SetMatrix("mENV", &mat);
  687.         }
  688.  
  689.         // Draw water
  690.         UINT uPasses;
  691.         m_pEffect->Begin(&uPasses, 0);
  692.  
  693.         for(UINT uPass = 0; uPass < uPasses; uPass++)
  694.         {
  695.             m_pEffect->Pass(uPass);
  696.             m_Water.DrawSurface();
  697.         }
  698.  
  699.         m_pEffect->End();
  700.     }
  701.  
  702.     // Show info
  703.     m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  704.     m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  705.  
  706.     TCHAR szText[100];
  707.     wsprintf( szText, _T("Using Technique %d"), m_iTechnique );
  708.     m_pFontSmall->DrawText( 2, 40, D3DCOLOR_ARGB(255,255,100,100), szText );
  709.     
  710.     if( m_bShowHelp )
  711.     {
  712.         m_pFontSmall->DrawText(  2, 60, D3DCOLOR_ARGB(255,100,100,200),
  713.                                 _T("Keyboard controls:") );
  714.         m_pFontSmall->DrawText( 20, 80, D3DCOLOR_ARGB(255,100,100,200),
  715.                                 _T("Add Drop\n")
  716.                                 _T("Next Technique\n")
  717.                                 _T("Next Tech. (no validate)\n")
  718.                                 _T("Prev Technique\n")
  719.                                 _T("Prev Tech. (no validate)\n")
  720.                                 _T("Move\nTurn\nPitch\nSlide\n")
  721.                                 _T("Help\nChange device\nExit") );
  722.         m_pFontSmall->DrawText( 210, 80, D3DCOLOR_ARGB(255,100,100,200),
  723.                                 _T("D\n")
  724.                                 _T("PageDn\nShift-PageDn\n")
  725.                                 _T("PageUp\nShift-PageUp\n")
  726.                                 _T("W,S\nE,Q\nA,Z\nArrow keys\n")
  727.                                 _T("F1\nF2\nEsc") );
  728.     }
  729.     else
  730.     {
  731.         m_pFontSmall->DrawText(  2, 60, D3DCOLOR_ARGB(255,100,100,200), 
  732.                            _T("Press F1 for help") );
  733.     }
  734.  
  735.  
  736.     if(FAILED(hr = m_pd3dDevice->EndScene()))
  737.         return hr;
  738.  
  739.     return S_OK;
  740. }
  741.  
  742.  
  743.  
  744.  
  745. //-----------------------------------------------------------------------------
  746. // Name: MsgProc
  747. // Desc:
  748. //-----------------------------------------------------------------------------
  749. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, 
  750.                                     LPARAM lParam )
  751. {
  752.     switch( uMsg )
  753.     {
  754.         case WM_KEYDOWN:
  755.             m_bKey[wParam] = TRUE;
  756.             break;
  757.  
  758.         case WM_KEYUP:
  759.             m_bKey[wParam] = FALSE;
  760.             break;
  761.  
  762.     case WM_COMMAND:
  763.         {
  764.             switch( LOWORD(wParam) )
  765.             {
  766.             case IDM_ADDDROP:
  767.                 m_Water.Drop();
  768.                 break;
  769.  
  770.             case IDM_NEXT_TECHNIQUE:
  771.                 GetNextTechnique(1, FALSE);
  772.                 break;
  773.  
  774.             case IDM_NEXT_TECHNIQUE_NOVALIDATE:
  775.                 GetNextTechnique(1, TRUE);
  776.                 break;
  777.  
  778.             case IDM_PREV_TECHNIQUE:
  779.                 GetNextTechnique(-1, FALSE);
  780.                 break;
  781.  
  782.             case IDM_PREV_TECHNIQUE_NOVALIDATE:
  783.                 GetNextTechnique(-1, TRUE);
  784.                 break;
  785.  
  786.             case IDM_TOGGLEHELP:
  787.                 m_bShowHelp = !m_bShowHelp;
  788.                 break;
  789.             }
  790.         }
  791.  
  792.     }
  793.  
  794.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  795. }
  796.  
  797.  
  798.